package com.wangshili.sys.service.Impl;

import java.util.List;
import java.util.UUID;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wangshili.common.exception.ServiceException;
import com.wangshili.pojo.sys.entity.SysUser;
import com.wangshili.sys.dao.SysUserDao;
import com.wangshili.sys.dao.SysUserRoleDao;
import com.wangshili.sys.service.SysUserService;
import com.wangshili.sys.vo.SysUserDept;
import com.wangshili.sys.vo.SysUserDeptRole;
/**
 * 服务层实现
 * @author wangshili 
 *
 */
@Service
public class SysUserServiceImpl implements SysUserService {
	private static final Logger log =
			LoggerFactory.getLogger(SysUserServiceImpl.class);
	
	/**
	 * 注入日志持久层接口
	 */
	@Autowired
	private SysUserDao sysUserDao;
	
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	/**
	 * 查询统计符合该名字的行数
	 * @param name 输入用户名字，模糊查询
	 * @return
	 */
	@Override
	public int intRowCount(String name) {
		int intRowCount = sysUserDao.countRowByName(name);
		log.debug("获取"+name+"行数："+intRowCount);
		return intRowCount;
	}
	
	/**
	 * 
	 * @param username 用户名称
	 * @param pageCurren 当前页码
	 * @return
	 */
	@Cacheable(value = "userDept")
	@Override
	public PageInfo<SysUserDept> listPageObject(String username, Integer pageCurrent) {
		log.debug("查询"+username+"用户当前"+pageCurrent+"页信息");
		//1.验证参数合法性
		if(pageCurrent == null || pageCurrent <1)//先判空再判小于，不能颠倒，不然先判小于1会出现空指针异常
			throw new IllegalArgumentException("当前页码不合法");
		//2.根据条件查询总记录数
		//int intRowCount = sysUserDao.countRowByName(username);
		//2.1判断查询的行数是否小于3
//		if(intRowCount<1)
//			throw new ServiceException("系统未找到相关信息");
		//3.查询指定用户信息
		int pageSize=10;//指定页面展现的行数
		//通过页数-1再乘页码大小得出当前页的位置，因为pageCurren起始是1，startIndex起始是0
//		int startIndex = (pageCurrent-1)*pageSize;
		//4.开启分页
		PageHelper.startPage(pageCurrent, pageSize);//输入当前页和页大小
		List<SysUserDept> logList = sysUserDao.listPageObject(username);
		if(logList==null || logList.size()<1)
			throw new ServiceException("系统未找到相关信息");
		PageInfo<SysUserDept> pageInfo = new PageInfo<SysUserDept>(logList);
		return pageInfo;
	}
	
	
	/**
	 * 根据id更新禁用状态
	 * @param id user的id
	 * @param valid 状态
	 * @param modifiedUser 修改人
	 * @return
	 */
	
	@Override
	public int updateValidById(Integer id, Integer valid,String modifiedUser) {
		//1.数据校验
		 if(id==null||id < 1)throw new ServiceException("参数不合法,id="+id);
         if(valid!=1&&valid!=0)throw new ServiceException("参数不合法,valie="+valid);
         if(StringUtils.isEmpty(modifiedUser))throw new ServiceException("修改用户不能为空");
		
         int rows = sysUserDao.updateValidById(id, valid,modifiedUser);
         if(rows<1)throw new ServiceException("此记录可能已经不存在");
         return rows;
	}
	
	
	/**
	 * 插入一条用户信息，并插入关系表
	 * @param entity 用户信息
	 * @param roleIds 对应的多个角色信息
	 * @return
	 */
	@CacheEvict(value = "userDept",allEntries = true)//清空全部缓存，指定allEntries全部，如果不指定key，则默认以参数作为Key查询                     
	@Override
	public int saveObject(SysUser entity, Integer[] roleIds) {
        long start=System.currentTimeMillis();
        log.info("start:"+start);
        //1.参数校验
        if(entity==null)
        	throw new IllegalArgumentException("保存对象不能为空");
        if(StringUtils.isEmpty(entity.getUsername()))
        	throw new IllegalArgumentException("用户名不能为空");
        if(StringUtils.isEmpty(entity.getPassword()))
        	throw new IllegalArgumentException("密码不能为空");
        if(roleIds==null || roleIds.length==0)
        	throw new IllegalArgumentException("至少要为用户分配角色");
        List<SysUserDept> listPageObject = 
        		sysUserDao.listPageObject(entity.getUsername());
        if(listPageObject!=null && listPageObject.size()>0)
        	throw new IllegalArgumentException("该用户已存在，请重新输入");
        //2.保存用户自身信息
        //2.1对密码进行加密
        String source=entity.getPassword();
        String salt=UUID.randomUUID().toString();
        SimpleHash sh=new SimpleHash(//Shiro框架
                        "MD5",//algorithmName 算法
                         source,//原密码
                         salt, //盐值
                         1);//hashIterations表示加密次数
        entity.setSalt(salt);
        entity.setPassword(sh.toHex());
        int rows=sysUserDao.insertObject(entity);
        //3.保存用户角色关系数据
        sysUserRoleDao.insertRoleMenu(entity.getId(), roleIds);
        long end=System.currentTimeMillis();
        log.info("end:"+end);
        log.info("total time :"+(end-start));
        //4.返回结果
        return rows;
	}
	
	
	/**
	 * 更新操作页面需要查找用户信息、部门信息、角色Ids
	 */
	@Override
	public SysUserDeptRole selectUserDeptRole(Integer id) {
		if(StringUtils.isEmpty(id))
			throw new IllegalArgumentException("用户标识不合法");
		SysUserDeptRole selectUserDeptRolIdsById = 
				sysUserDao.selectUserDeptRolIdsById(id);
		if(selectUserDeptRolIdsById==null)
			throw new ServiceException("此记录可能已经不存在");
		return selectUserDeptRolIdsById;
	}
	
	
	/**
	 * 更新用户信息，再根据用户id删除对应的角色信息，再插入客户端传过来的新角色
	 * 信息
	 * @param entity 用户信息
	 * @param userId 用户id
	 * @return
	 */
	//@CachePut(value = "userDept",key="#entity.id")//这里只能全部移除了，存入缓存时的参数不一样
	@CacheEvict(value = "userDept",allEntries = true)
	@Override
	public int updateUserAndRole(SysUser entity, Integer... roleIds) {
		if(StringUtils.isEmpty(entity))
			throw new IllegalArgumentException("用户信息不合法");
		if(roleIds==null || roleIds.length<1)
			throw new IllegalArgumentException("未指定角色");
		if(StringUtils.isEmpty(entity.getUsername()))
			throw new IllegalArgumentException("必须制定用户名");

		//插入用户信息
		int rowsUser = 
				sysUserDao.updateObject(entity);
		if(rowsUser<1)
			throw new ServiceException("更新的用户可能不存在");
		//删除用户id对应的角色信息
		sysUserRoleDao.deleteObjectByUserId(entity.getId());
		//插入用户id对应的角色信息
		int rowsUserRole = 
				sysUserRoleDao.insertRoleMenu(entity.getId(), roleIds);
		if(rowsUserRole<1)
			throw new ServiceException("更新的角色关系可能不存在");

		return rowsUser;
	}

	
	
	/**
	 * 更新密码
	 * @param password 原密码
	 * @param newPassword 新密码
	 * @param cfgPassword 再次输入的新密码
	 * @return
	 */
	@Override
	public int updatePassword(String password, String newPassword, String cfgPassword) {
		//1.判定新密码与密码确认是否相同
        if(StringUtils.isEmpty(newPassword))
        	throw new IllegalArgumentException("新密码不能为空");
        if(StringUtils.isEmpty(cfgPassword))
        	throw new IllegalArgumentException("确认密码不能为空");
        if(!newPassword.equals(cfgPassword))
        	throw new IllegalArgumentException("两次输入的密码不相等");

        //2.判定原密码是否正确
        if(StringUtils.isEmpty(password))
        	throw new IllegalArgumentException("原密码不能为空");

        //获取登陆用户
        SysUser user=(SysUser)SecurityUtils.getSubject().getPrincipal();
        SimpleHash sh=new SimpleHash("MD5",
        password, user.getSalt(), 1);//根据密码和盐值生成它的md5密码进行对比
        if(!user.getPassword().equals(sh.toHex()))
        	throw new IllegalArgumentException("原密码不正确");

        //3.对新密码进行加密
        String salt=UUID.randomUUID().toString();//随机的盐值
        sh=new SimpleHash("MD5",newPassword,salt, 1);

        //4.将新密码加密以后的结果更新到数据库
        int rows=sysUserDao.updatePassword(sh.toHex(), salt,user.getId());
        if(rows==0)
        	throw new ServiceException("修改失败");
        return rows;
	}

}
